/**
 * @File   : WebUpload.js
 * @Author : xue.xiaoBing
 * @Date   : 2020/12/9
 * @Desc   : 基于webUploader的
 *           大文件断点续传组件
 **/

import {connect} from "react-redux";
import React, {Component} from 'react';
import {Table, Button, Row, Progress, Space, Tag} from "antd";

import {checkChunk, mergeChunk, checkFile} from "src/api/request";
import webUpload from "src/assets/package/webUploader/webuploader-all";
import uploaderSwf from "src/assets/package/webUploader/Uploader.swf";

import {DeleteFilled, PauseCircleFilled, PlayCircleFilled, ExclamationCircleOutlined} from "@ant-design/icons";

import "./WebUpload.sass";


class WebUpload extends Component {
  constructor(props) {
    super(props);
    this.state = {
      initUpload: {
        auto: true,
        threads: 7,
        chunked: true,
        chunkRetry: 2,
        resize: false,
        multiple: true,
        method: 'POST',
        pick: '#picker',
        sendAsBinary: true,
        server: '/api/v1/project/' + this.props.project_id + '/datas/upload_chunk',
        chunkSize: 10 * 1024 * 1024,
        fileSizeLimit: 1024 * 1024 * 1024 * 100,
        fileSingleSizeLimit: 1024 * 1024 * 1024 * 5,
        accept: {
          extensions: "txt,jpg,jpeg,bmp,png,zip,rar,war,pdf,cebx,doc,docx,ppt,pptx,xls,xlsx,iso,flv,mp4",
          mimeTypes: '.txt,.jpg,.jpeg,.bmp,.png,.zip,.rar,.war,.pdf,.cebx,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.iso,.flv,.mp4'
        },
      },
      uploadList: []
    }
  }

  componentDidMount() {

    let that = this;
    let state = 'pending';

    // 注册监听函数
    webUpload.Uploader.register(
      {
        "before-send-file": "beforeSendFile",
        "before-send": "beforeSend",
        "after-send-file": "afterSendFile",
      }, {
        // 修改文件页面显示状态
        beforeSendFile: function (file) {
          let deferred = webUpload.Deferred();
          (new webUpload.Uploader()).md5File(file)
            .progress(function (percentage) {
            })
            .then(function (val) {
              file.md5 = val;
            });
          console.log(file, 'upload file...')
          that.props.checkFile(
            {
              // fileMd5: file.md5,
              fileName: file.name,
              project_id: that.props.project_id,
            }
          ).then(
            ret => {
              console.log('接受返回...', ret)
              if (ret.isExist) {
                deferred.reject()
              } else {
                deferred.resolve()
              }
            }
          );
          return deferred.promise()
        },
        // 分片上传前检测
        beforeSend: function (block) {
          console.log("beforeSend------------------->", block);
          let deferred = webUpload.Deferred();

          that.props.checkChunk(
            {
              // fileMd5: block.cuted.file.md5,
              chunk: block.chunk,
              chunkSize: block.end - block.start,
              project_id: that.props.project_id,
            }
          ).then(
            ret => {
              if (ret.isExist) {
                deferred.reject()
              } else {
                deferred.resolve()
              }
            }
          )

        },
        // 分片上传成功后
        afterSendFile: function (file) {
          console.log("afterSendFile------------------->", file);
          that.props.mergeChunk({
            fileId: file.id,
            // fileMd5: file.md5,
            fileName: file.name,
            project_id: that.props.project_id,
          }).then(
            res => {
              console.log(res.fileName + '上传成功...')
            }
          )
        }
      }
    );

    // 实例化
    this.WU = webUpload.create({
      pick: {
        id: '#picker',
        multiple: true,
      },
      auto: false,
      // SWF
      swf: uploaderSwf,
      // 配置分片
      chunked: this.state.initUpload.chunked,
      // 配置接受文件类型
      accept: this.state.initUpload.accept,
      // 配置请求方式
      method: this.state.initUpload.method,
      // 配置压缩模式
      resize: this.state.initUpload.resize,
      // 配置线程数
      threads: this.state.initUpload.threads,
      // 配置分片大小
      chunkSize: this.state.initUpload.chunkSize,
      // 配置二进制
      // sendAsBinary: this.state.initUpload.sendAsBinary,
      // 配置总文件限制
      fileSizeLimit: this.state.initUpload.fileSizeLimit,
      // 配置单个文件限制
      fileSingleSizeLimit: this.state.initUpload.fileSingleSizeLimit,
      // 配置文件上传服务
      server: this.state.initUpload.server,
      prepareNextFile: true
    });


    this.WU.on('fileQueued', function (file) {
      let fileSize;
      if (file.size < 1024) {
        fileSize = file.size.toString() + ' B'
      } else if (file.size >= 1024 && file.size < 1024 * 1024) {
        fileSize = (file.size / 1024).toFixed(1).toString() + ' K'
      } else if (file.size >= 1024 * 1024 && file.size < 1024 * 1024 * 1024) {
        fileSize = (file.size / (1024 * 1024)).toFixed(1).toString() + ' M'
      } else {
        fileSize = (file.size / (1024 * 1024 * 1024)).toFixed(1).toString() + ' G'
      }

      that.setState({
        ...that.state,
        uploadList: [
          ...that.state.uploadList,
          {
            index: parseInt(file.id.split('_')[2]) + 1,
            key: file.name,
            fileName: file.name,
            fileSize: fileSize,
            filePercentage: 0,
            fileState: 0,
            action: false,
            file: file
          }
        ]
      })
    });

    // 进度条
    this.WU.on('uploadProgress', function (file, percentage) {
      that.setState({
        ...that.state,
        uploadList: (that.state.uploadList.map(
            (item) => item.fileName === file.name ? {
              ...item,
              fileState: 1,
              filePercentage: parseInt(percentage * 100).toString()
            } : item
          )
        )
      })
    });

    // 上传成功
    this.WU.on('uploadSuccess', function (file) {
      that.setState({
        ...that.state,
        uploadList: (that.state.uploadList.map((item) => item.fileName === file.name ? {
            ...item,
            fileState: 2
          } : item)
        )
      })
    });

    // 上传出错
    this.WU.on('uploadError', function (file) {
      that.setState({
        ...that.state,
        uploadList: (that.state.uploadList.map((item) => item.fileName === file.name ? {
            ...item,
            fileState: 4
          } : item)
        )
      })
    });

    // 上传完成
    this.WU.on('uploadComplete', function (file) {

    });

    this.WU.on('stopUpload', function (file) {

    });

    // 全部上传
    this.WU.on('all', function (type) {
      if (type === 'startUpload') {
        state = 'uploading';
      } else if (type === 'stopUpload') {
        state = 'paused';
      } else if (type === 'uploadFinished') {
        state = 'done';
      }
    });


  }

  startUpload = () => {
    this.WU.upload()
  };

  stopUpload = (file) => {
    this.setState({
      ...this.state,
      uploadList: (this.state.uploadList.map((item) => item.fileName === file.name ? {
          ...item,
          fileState: 3,
          action: !item.action,
        } : item)
      )
    });
    console.log('stopFile start...')
    this.WU.cancelFile(file)
    console.log('stopFile end...')
  };

  retryUpload = (file) => {
    this.setState({
      ...this.state,
      uploadList: (this.state.uploadList.map((item) => item.fileName === file.name ? {
          ...item,
          fileState: 3,
          action: !item.action,
        } : item)
      )
    });
    webUpload.Deferred().resolve()
    console.log('retryUpload');
    this.WU.upload(file)
  };

  deleteFile = (file) => {
    console.log(file.name)
    this.setState({
      ...this.state,
      uploadList: (this.state.uploadList.filter((item) => item.fileName !== file.name))
    });
    this.WU.cancelFile(file);
  };


  render() {
    const {uploadList} = this.state;
    const columns = [
      {
        title: '序号',
        dataIndex: 'index',
        key: 'index',
        align: 'center',
      }, {
        title: '文件名',
        dataIndex: 'fileName',
        key: 'fileName',
        align: 'center',
      }, {
        title: '文件大小',
        dataIndex: 'fileSize',
        key: 'fileSize',
        align: 'center',
      }, {
        title: '文件进度',
        dataIndex: 'filePercentage',
        key: 'filePercentage',
        align: 'center',
        render: (filePercentage) =>
          <Progress strokeColor={{
            from: '#108ee9',
            to: '#87d068',
          }} percent={filePercentage} status="active"/>
      }, {
        title: '文件状态',
        dataIndex: 'fileState',
        key: 'fileState',
        align: 'center',
        render: (fileState) => {
          if (fileState === 0) {
            return <Tag color={'geekblue'}>等待上传</Tag>
          } else if (fileState === 1) {
            return <Tag color={'volcano'}>正在上传.</Tag>
          } else if (fileState === 2) {
            return <Tag color={'green'}>完成上传</Tag>
          } else if (fileState === 3) {
            return <Tag color={'blue'}>暂停上传</Tag>
          } else if (fileState === 4) {
            return <Tag color={'red'}>上传出错</Tag>
          }
        }
      }, {
        title: '操作',
        dataIndex: 'action',
        key: 'action',
        align: 'center',
        render: (action, file) =>
          <Space size={'middle'}>
            {action === false ?
              <PlayCircleFilled onClick={this.retryUpload.bind(this, file.file)}/>
              :
              <PauseCircleFilled style={{color: 'blue'}} onClick={this.stopUpload.bind(this, file.file)}/>
            }
            <DeleteFilled style={{color: '#ff4d4f'}} onClick={this.deleteFile.bind(this, file.file)}/>
          </Space>
      }
    ];
    return (
      <div className={'web-upload'}>
        <Table columns={columns} dataSource={uploadList} pagination={{defaultPageSize: 3}}/>
        <Row className={'upload-table'}>
          <div id="picker">选择文件</div>
          <Button type={'primary'} className={'upload-button'} onClick={this.startUpload}>开始上传</Button>
        </Row>
      </div>
    )
  }
}

export default connect(
  null,
  {
    checkFile,
    checkChunk,
    mergeChunk,
  }
)
(WebUpload)